<?php
/**
 * @author spenceryg
 * @date 2022/4/14
 * @time 9:20 上午
 * @focus love & life
 */
declare (strict_types = 1);


namespace app\common\lib\verify;


use app\common\lib\verify\interfaces\Verify;
use think\Exception;
use think\exception\ValidateException;
use think\facade\Cache;
use think\facade\Log;

class VerifyFactory
{
    protected $verify = null;
    protected $to = '';
    protected $code = '';

    public function __construct(Verify $verify)
    {
        $this->verify = $verify;
    }

    /**
     * setCode
     * @param int $length
     * @param string|array $code
     * @return $this
     */
    public function setCode(int $length = 6,  $code = ''): VerifyFactory
    {
        if (!$code) {
            for ($i = 0; $i < $length; $i++) {
                $code .= rand(0, 9);
            }
        }
        $this->code = $code;
        return $this;
    }

    /**
     * setTo
     * @param string $to
     * @return $this
     */
    public function setTo(string $to): VerifyFactory
    {
        $this->to = $to;
        return $this;
    }

    /**
     * send
     */
    public function send()
    {
        try{
            self::checkTimeDiff($this->to);
            self::checkTimeCount($this->to);
            $this->verify->sendCode($this->to, $this->code);
            self::setCache($this->to, $this->code);
        }catch (\Exception $e){
            Log::error($e, [$this->to, $this->code]);
            throw new ValidateException('验证码发送错误！' . $e->getMessage());
        }
    }


    /**
     * verify
     * @param string $to
     * @param string $code
     * @throws \Exception
     */
    public static function verify(string $to, string $code)
    {
        $sendCode = Cache::get('code_' . $to);
        if ($sendCode != $code || !$sendCode) {
            throw new ValidateException('验证码错误或已过期');
        }
        else {
            self::unSetCache($to);
        }
    }


    /**
     * 2次发送不能小于1分钟
     * checkTimeDiff
     */
    protected static function checkTimeDiff(string $to)
    {
        $last_time = Cache::get('time_' . $to) ?: 0;
        if (time() - $last_time < 60) {
            throw new ValidateException('请求过于频繁，2次请求需要大于1分钟。');
        }
    }

    /**
     * 30分钟内不能超过5次
     * checkTimeCount
     */
    protected static function checkTimeCount($to)
    {
        if ((Cache::get('count_'. $to)?:0) > 5) {
            throw new \Exception('请求过于频繁，请30分钟后再请求。');
        }
    }


    /**
     * 设置缓存
     * setCache
     */
    protected function setCache(string $to, string $code){
        Cache::set('code_' . $to, $code, 300);
        Cache::set('time_' . $to, time(), 300);
        Cache::set('count_' . $to, (Cache::get('count_'. $to)?:0) + 1, 300);
    }

    /**
     * 删除缓存
     * unSetCache
     */
    public static function unSetCache(string $to){
        Cache::set('code_' . $to, null);
        Cache::set('time_' . $to, null);
        Cache::set('count_' . $to, null);
    }


}
